package stat;

public class GaussianModel {

	private double theta; // mean

	private double delta; // var

	private static final double PI2 = Math.sqrt(2 * Math.PI);

	private double pi2delta, delta2;

	public GaussianModel(double mean, double var) {
		theta = mean;
		delta = var;
		update();
	}

	public GaussianModel(double x[]) {
		this(calcMean(x), calcDev(x));
	}

	public static double calcMean(double x[]) {
		double sum = 0;
		for (int i = 0; i < x.length; i++) {
			sum += x[i];
		}
		return sum / (double)x.length;
	}

	public static double calcMeanBetween(double x[], int s, int e) {
		double sum = 0;
		for (int i = s; i < e; i++) {
			sum += x[i];
		}
		return sum / (double)(e - s);
	}

	public static double calcDev(double x[]) {
		double mean = calcMean(x);
		double var = 0;
		for (int i = 0; i < x.length; i++) {
			var += (x[i] - mean) * (x[i] - mean);
		}
		return Math.sqrt(var / (double)(x.length - 1));
	}

	public static double calcDevBetween(double x[], int s, int e) {
		double mean = calcMeanBetween(x, s, e);
		double var = 0;
		for (int i = s; i < e; i++) {
			var += (x[i] - mean) * (x[i] - mean);
		}
		return Math.sqrt(var / (double)(e - s - 1));
	}

	private void update() {
		pi2delta = PI2 * getDelta();
		delta2 = 2 * getDelta() * getDelta();
	}

	public double getTheta() {
		return theta;
	}

	public void setTheta(double theta) {
		this.theta = theta;
	}

	public double getDelta() {
		return delta;
	}

	public void setDelta(double delta) {
		this.delta = delta;
		update();
	}

	public double calcValue(double x) {
		return Math.exp( -(x - getTheta()) * (x - getTheta()) /
                delta2) / pi2delta;
	}

	public double[] calcValues(double x[]) {
//		System.out.println("GM mean=" + getTheta() + ", var=" + getDelta());
		double v[] = new double[x.length];
		for (int i = 0; i < v.length; i++) {
			v[i] = calcValue(x[i]);
		}
		return v;
	}
}
